﻿using Furion.DatabaseAccessor;
using Mapster;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading;
using System.Threading.Tasks;
using UpperComputer.Core.Entities;
using YFurion.Application;
using YFurion.Application.EFCore.Extensions;
using YFurion.Collections.Extensions;
using YFurion.DataFilters;
using YFurion.Extensions;

namespace UpperComputer.Application
{
    public class BaseMenuService : EFCoreApplicationService<BaseMenu, BaseMenuResultDto, long, BaseMenuResultRequestDto, BaseMenuDto>, IBaseMenuService
    {
        private readonly IDataFilter _dataFilter;
        public BaseMenuService(IDataFilter dataFilter)
        {
            _dataFilter = dataFilter;
        }

        #region 获取树形菜单
        /// <summary>
        /// 获取树形菜单
        /// </summary>
        /// <param name="input"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<List<BaseMenuResultDto>> GetMenus(BaseMenuResultRequestDto input, CancellationToken cancellationToken = default)
        {
            PagedResultDto<BaseMenuResultDto> pagedResultDto = await GetAll(input, cancellationToken);
            List<BaseMenuResultDto> baseMenuResultDtos = GetMenus(pagedResultDto.Items, "", input);
            return baseMenuResultDtos;
        }

        private List<BaseMenuResultDto> GetMenus(IReadOnlyList<BaseMenuResultDto> baseMenuResultDtos, string parentCode, BaseMenuResultRequestDto baseMenuResultRequestDto)
        {
            List<BaseMenuResultDto> resultDtos = new List<BaseMenuResultDto>();
            foreach (BaseMenuResultDto baseMenuResultDto in baseMenuResultDtos)
            {
                if (!parentCode.Equals(baseMenuResultDto.ParentCode))
                {
                    continue;
                }

                string code = baseMenuResultRequestDto.Code;
                if (!code.IsNullOrWhiteSpace() && code.Equals(baseMenuResultDto.Code))
                {
                    continue;
                }

                baseMenuResultDto.Childrens = GetMenus(baseMenuResultDtos, baseMenuResultDto.Code, baseMenuResultRequestDto);
                resultDtos.Add(baseMenuResultDto);

                if (baseMenuResultDto.BaseMenuButton.Count > 0 &&
                baseMenuResultRequestDto.CanSearchMenuButtons)
                {
                    baseMenuResultDto.BaseMenuButton = baseMenuResultDto.BaseMenuButton.WhereIf(baseMenuResultRequestDto.IsActive != null, bmb => bmb.IsActive == baseMenuResultRequestDto.IsActive).OrderBy(bmb => bmb.Sort).ToList();
                    if (baseMenuResultRequestDto.ShowMenuButtons)
                    {
                        baseMenuResultDto.Childrens = new List<BaseMenuResultDto>();
                        foreach (BaseMenuButtonResultDto item in baseMenuResultDto.BaseMenuButton)
                        {
                            BaseMenuResultDto baseMenuButtonResultDto = item.Adapt<BaseMenuResultDto>();
                            baseMenuButtonResultDto.ParentCode = baseMenuResultDto.Code;
                            baseMenuButtonResultDto.Type = 2;
                            baseMenuResultDto.Childrens.Add(baseMenuButtonResultDto);
                        }
                    }
                }
            }
            return resultDtos.Count > 0 ? resultDtos : null;
        }

        protected override IQueryable<BaseMenu> CreateFilteredQuery(BaseMenuResultRequestDto input)
        {
            IQueryable<BaseMenu> query = input.CanSearchMenuButtons ? MasterRepository.Include(bm => bm.BaseMenuButton) : MasterRepository.AsQueryable()
                .WhereIf(input.IsActive != null, bm => bm.IsActive == input.IsActive);
            return query;
        }
        #endregion

        #region 新增
        public override async Task<BaseMenuResultDto> Post(BaseMenuDto input, CancellationToken cancellationToken = default)
        {
            //忽略查询过滤方式一，只忽略禁止的过滤字段
            using (_dataFilter.DisableFilter(DataFilterConst.SoftDelete))
            {
                BaseMenu baseMenu = await MasterRepository.FirstOrDefaultAsync(bm => bm.Code.Equals(input.Code), cancellationToken: cancellationToken);
                if (baseMenu != null && !baseMenu.IsDeleted)
                {
                    throw Oh("编码已存在");
                }

                BaseMenuResultDto baseMenuResultDto = null;
                if (baseMenu == null)
                {
                    baseMenuResultDto = await base.Post(input, cancellationToken);
                }
                else
                {
                    input.Id = baseMenu.Id;
                    baseMenu.IsDeleted = false;
                    baseMenuResultDto = await UpdateAsync(input, baseMenu, cancellationToken);
                }
                return baseMenuResultDto;
            }

            //忽略查询过滤方式二，忽略所有的过滤字段
            //BaseMenu baseMenu = await MasterRepository.AsQueryable(bm => bm.Code.Equals(input.Code), ignoreQueryFilters: true).FirstOrDefaultAsync(cancellationToken);
            //if (baseMenu != null && !baseMenu.IsDeleted)
            //{
            //    throw Oh("编码已存在");
            //}

            //BaseMenuResultDto baseMenuResultDto = null;
            //if (baseMenu == null)
            //{
            //    baseMenuResultDto = await base.Post(input, cancellationToken);
            //}
            //else
            //{
            //    input.Id = baseMenu.Id;
            //    baseMenu.IsDeleted = false;
            //    baseMenuResultDto = await UpdateAsync(input, baseMenu, cancellationToken);
            //}
            //return baseMenuResultDto;
        }
        #endregion

        #region 修改
        protected override async Task OnUpdateExecuting(BaseMenu entity, CancellationToken cancellationToken)
        {
            await base.OnUpdateExecuting(entity, cancellationToken);
            BaseMenu baseMenu = await MasterRepository.FirstOrDefaultAsync(bm => !bm.Id.Equals(entity.Id) && bm.Code.Equals(entity.Code), cancellationToken: cancellationToken);
            if (baseMenu != null)
            {
                throw Oh("编码不存在或已被删除");
            }
        }

        #endregion
    }
}
